在 iOS App 裡,Apple 提供了兩種原生持久化儲存資料的方式
一種是今天要講的 UserDefaults、一種是 CoreData
CoreData 是屬於資料庫方面的資料儲存解決方案,不是今天的主角,所以就先不討論
UserDefaults 是一種 Key-Value 的簡易、持久性儲存資料的方式
提供了 String、Array、Dictionary、Data、String Array、Int、Float、Double、Bool、URL 等儲存格式
// 取自 Xcode 內的 Foundation/NSUserDefaults/UserDefaults
open func string(forKey defaultName: String) -> String?
open func array(forKey defaultName: String) -> [Any]?
open func dictionary(forKey defaultName: String) -> [String : Any]?
open func data(forKey defaultName: String) -> Data?
open func stringArray(forKey defaultName: String) -> [String]?
open func integer(forKey defaultName: String) -> Int
open func float(forKey defaultName: String) -> Float
open func double(forKey defaultName: String) -> Double
open func bool(forKey defaultName: String) -> Bool
@available(iOS 4.0, *)
open func url(forKey defaultName: String) -> URL?
所以就來將 UserDefaults 寫成一個 class 來管理吧
class UserPreference {
static let shared = UserPreference()
private let userPreference: UserDefaults
private init() {
userPreference = UserDefaults.standard
}
}
UserDefaults 的給值、讀值方式如下~
// 給值
// 你要給這個值的 Key,要用 String 來表示
userPreference.set(你要給的值, forKey: 你要給這個值的 Key)
// 讀值
// 根據你要給的值的型態來決定
// Int
userPreference.integer(forKey: 你要讀的那個值的 Key)
// String
userPreference.string(forKey: 你要讀的那個值的 Key)
// Float
userPreference.float(forKey: 你要讀的那個值的 Key)
// Double
userPreference.double(forKey: 你要讀的那個值的 Key)
// Data
userPreference.data(forKey: 你要讀的那個值的 Key)
// String Array
userPreference.stringArray(forKey: 你要讀的那個值的 Key)
// Bool
userPreference.bool(forKey: 你要讀的那個值的 Key)
// Dictionary
userPreference.dictionary(forKey: 你要讀的那個值的 Key)
// Array
userPreference.array(forKey: 你要讀的那個值的 Key)
// URL
userPreference.url(forKey: 你要讀的那個值的 Key)
然後 Key 的部分,我們可以寫一個 enum 來管理,像是下面這樣
enum UserPreference: String {
case email // 使用者的 Email
case username // 使用者的名字
case age // 使用者的年齡
case height // 使用者的身高
case weight // 使用者的體重
case isActivate // 使用者的帳號啟用狀態
}
然後在讀值、給值方面,可以像下面這樣寫,透過 get/set 的方式來完成
var email: String {
get { return userPreference.string(forKey: UserPreference.email.rawValue) ?? "" }
set { return userPreference.set(newValue, forKey: UserPreference.email.rawValue) }
}
var username: String {
get { return userPreference.string(forKey: UserPreference.username.rawValue) ?? "" }
set { return userPreference.set(newValue, forKey: UserPreference.username.rawValue) }
}
var age: Int {
get { return userPreference.integer(forKey: UserPreference.age.rawValue) }
set { return userPreference.set(newValue, forKey: UserPreference.age.rawValue) }
}
var height: Double {
get { return userPreference.double(forKey: UserPreference.height.rawValue) }
set { return userPreference.set(newValue, forKey: UserPreference.height.rawValue) }
}
var weight: Double {
get { return userPreference.double(forKey: UserPreference.weight.rawValue) }
set { return userPreference.set(newValue, forKey: UserPreference.weight.rawValue) }
}
var isActivate: Bool {
get { return userPreference.bool(forKey: UserPreference.isActivate.rawValue) }
set { return userPreference.set(newValue, forKey: UserPreference.isActivate.rawValue) }
}
所以整個 class 就會長得像是下面這樣~
class UserPreference {
static let shared = UserPreference()
private let userPreference: UserDefaults
private init() {
userPreference = UserDefaults.standard
}
enum UserPreference: String {
case email // 使用者的 Email
case username // 使用者的名字
case age // 使用者的年齡
case height // 使用者的身高
case weight // 使用者的體重
case isActivate // 使用者的帳號啟用狀態
}
var email: String {
get { return userPreference.string(forKey: UserPreference.email.rawValue) ?? "" }
set { return userPreference.set(newValue, forKey: UserPreference.email.rawValue) }
}
var username: String {
get { return userPreference.string(forKey: UserPreference.username.rawValue) ?? "" }
set { return userPreference.set(newValue, forKey: UserPreference.username.rawValue) }
}
var age: Int {
get { return userPreference.integer(forKey: UserPreference.age.rawValue) }
set { return userPreference.set(newValue, forKey: UserPreference.age.rawValue) }
}
var height: Double {
get { return userPreference.double(forKey: UserPreference.height.rawValue) }
set { return userPreference.set(newValue, forKey: UserPreference.height.rawValue) }
}
var weight: Double {
get { return userPreference.double(forKey: UserPreference.weight.rawValue) }
set { return userPreference.set(newValue, forKey: UserPreference.weight.rawValue) }
}
var isActivate: Bool {
get { return userPreference.bool(forKey: UserPreference.isActivate.rawValue) }
set { return userPreference.set(newValue, forKey: UserPreference.isActivate.rawValue) }
}
}
在其他檔案呼叫的時候就可以像下面這樣來呼叫~
var email: String = UserPreference.shared.email
var username: String = UserPreference.shared.username
var age: Int = UserPreference.shared.age
var height: Double = UserPreference.shared.height
var weight: Double = UserPreference.shared.weight
var isActivate: Bool = UserPreference.shared.isActivate
這樣 Code 看起來就會清晰很多了~
這樣也同時解決去年實作 Firebase Auth 登入,重開 App 沒辦法紀錄登入狀態的問題~